
#include <scott/SEnum.h>

BOOST_AUTO_TEST_SUITE( SEnum_Test_Suite )

BOOST_AUTO_TEST_CASE( SEnumTypeDescriptor_Test )
{
	SEnumTypeDescriptorSp etd = SEnumTypeDescriptor::Create("plugin", "colors", "A color enum descriptor");

	BOOST_CHECK( etd->GetName() == "colors");
	BOOST_CHECK( etd->GetPluginName() == "plugin");
	BOOST_CHECK( etd->GetFullyQualifiedName() == "plugin.colors");
	BOOST_CHECK( etd->GetDescription() == "A color enum descriptor");
	BOOST_CHECK( etd->GetNumberOfEntries() == 0 );		
	BOOST_CHECK( etd->Describe(STypeEnum) == true );		
	BOOST_CHECK( etd->GetDescribedType() == STypeEnum );		
	
	BOOST_CHECK_THROW( etd->AddEntry("", 0, ""), SArgumentException ); 	// invalid key

	etd->AddEntry("red", 0, "red color");
	BOOST_CHECK( etd->GetNumberOfEntries() == 1 );

	BOOST_CHECK_THROW( etd->AddEntry("red", 1, ""), SArgumentException );     // duplicated key			
	BOOST_CHECK_THROW( etd->AddEntry("yellow", 0, ""), SArgumentException );  // duplicated value
	BOOST_CHECK( etd->GetNumberOfEntries() == 1 );

	etd->AddEntry("yellow", 1, "yellow color");
	etd->AddEntry("green", 2, "green color");

	BOOST_CHECK( etd->GetNumericValue("red") == 0 );
	BOOST_CHECK( etd->GetNumericValue("yellow") == 1 );
	BOOST_CHECK( etd->GetNumericValue("green") == 2 );
	BOOST_CHECK_THROW( etd->GetNumericValue("blue"), SArgumentException );    // invalid key

	BOOST_CHECK( etd->IsDefined("red") );
	BOOST_CHECK( etd->IsDefined("yellow") );
	BOOST_CHECK( etd->IsDefined("green") );
	BOOST_CHECK( etd->IsDefined("blue") == false );

	BOOST_CHECK( etd->IsDefined(0) );
	BOOST_CHECK( etd->IsDefined(1) );
	BOOST_CHECK( etd->IsDefined(2) );
	BOOST_CHECK( etd->IsDefined(3) == false );
}

BOOST_AUTO_TEST_CASE( SEnumTypeDescriptor_ValidKey_Test )
{
	SEnumTypeDescriptorSp etd = SEnumTypeDescriptor::Create("plugin", "enum", "");

	BOOST_CHECK_NO_THROW( etd->AddEntry("red", 0, "") );
	BOOST_CHECK_NO_THROW( etd->AddEntry("_red", 1, "") );
	BOOST_CHECK_NO_THROW( etd->AddEntry("_r12", 2, "") );
	BOOST_CHECK_NO_THROW( etd->AddEntry("a_2", 3, "") );
	BOOST_CHECK_NO_THROW( etd->AddEntry("ReD", 4, "") );

	BOOST_CHECK_THROW( etd->AddEntry("0red", 5, ""), SArgumentException );
	BOOST_CHECK_THROW( etd->AddEntry("_a-Z", 6, ""), SArgumentException );
	BOOST_CHECK_THROW( etd->AddEntry("r e d", 7, ""), SArgumentException );
}

BOOST_AUTO_TEST_CASE( Create_Test )
{
	// I control that is impossible to create a SEnum with an invalid enum type descriptor

	SEnumTypeDescriptorSp etd = SEnumTypeDescriptor::Create("plugin", "colors", "");
	BOOST_CHECK_THROW( SEnum::Create(etd, ""), SArgumentException );  

	etd->AddEntry("red", 0, "red color");			
	BOOST_CHECK_NO_THROW( SEnum::Create(etd, "red") );

	etd->AddEntry("yellow", 1, "yellow color");
	BOOST_CHECK_NO_THROW( SEnum::Create(etd, "yellow") );

	etd->AddEntry("green", 2, "green color");
	BOOST_CHECK_NO_THROW( SEnum::Create(etd, "green") );
}

BOOST_AUTO_TEST_CASE( SetGet_Test )
{
	//SEnumTypeDescriptorSp etd = 
	//	SEnumTypeDescriptor::Create("plugin", "colors", "A color enumerator.");
	//
	//etd->AddEntry("red", 0, "red color");			
	//etd->AddEntry("yellow", 1, "yellow color");
	//etd->AddEntry("green", 2, "green color");

	//SEnumSp e = SEnum::Create(etd, "red");

	//string val = e->Get();
	//unsigned long num = e->GetNumericValue();

	// Data
	SEnumTypeDescriptorSp etd = SEnumTypeDescriptor::Create("plugin", "colors", "");
	etd->AddEntry("red", 0, "red color");			
	etd->AddEntry("yellow", 1, "yellow color");
	etd->AddEntry("green", 2, "green color");

	// Test
	SEnumSp e = SEnum::Create(etd, "red");
	
	BOOST_CHECK(e->GetTypeDescriptor() == etd);			
	BOOST_CHECK(e->GetType() == STypeEnum);			
	BOOST_CHECK(e->Get() == "red");
	BOOST_CHECK(e->GetNumericValue() == 0);

	e->Set("yellow");

	BOOST_CHECK(e->Get() == "yellow");
	BOOST_CHECK(e->GetNumericValue() == 1);

	e->Set("green");

	BOOST_CHECK(e->Get() == "green");
	BOOST_CHECK(e->GetNumericValue() == 2);
}

BOOST_AUTO_TEST_CASE( Enum_From_Value_Test )
{
	// Data
	SEnumTypeDescriptorSp etd = SEnumTypeDescriptor::Create("plugin", "colors", "");
	etd->AddEntry("red", 0, "red color");			
	etd->AddEntry("yellow", 1, "yellow color");
	etd->AddEntry("green", 2, "green color");

	// Test
	SEnumSp e = SEnum::Create(etd, 0);

	BOOST_CHECK(e->GetTypeDescriptor() == etd);			
	BOOST_CHECK(e->GetType() == STypeEnum);			
	BOOST_CHECK(e->Get() == "red");
	BOOST_CHECK(e->GetNumericValue() == 0);

	e->Set(1);

	BOOST_CHECK(e->Get() == "yellow");
	BOOST_CHECK(e->GetNumericValue() == 1);

	e->Set(2);

	BOOST_CHECK(e->Get() == "green");
	BOOST_CHECK(e->GetNumericValue() == 2);
}

BOOST_AUTO_TEST_CASE( ToString_Test )
{
	// Data
	SEnumTypeDescriptorSp etd = SEnumTypeDescriptor::Create("plugin", "colors", "");
	etd->AddEntry("red", 0, "red color");			
	etd->AddEntry("yellow", 1, "yellow color");
	etd->AddEntry("green", 2, "green color");

	// Test
	SEnumSp e1 = SEnum::Create(etd, "red");
	SEnumSp e2 = SEnum::Create(etd, "yellow");
	SEnumSp e3 = SEnum::Create(etd, "green");

	BOOST_CHECK( e1->ToString() == "red" );
	BOOST_CHECK( e2->ToString() == "yellow" );
	BOOST_CHECK( e3->ToString() == "green" );
}

BOOST_AUTO_TEST_CASE( SEnum_Parse_Test )
{
	// Data
	SEnumTypeDescriptorSp etd = SEnumTypeDescriptor::Create("plugin", "colors", "");
	etd->AddEntry("red", 0, "red color");			
	etd->AddEntry("yellow", 1, "yellow color");
	etd->AddEntry("green", 2, "green color");

	// Test
	BOOST_CHECK( SEnum::Parse(etd, " red ")->Get() == "red" );
	BOOST_CHECK( SEnum::Parse(etd, " yellow ")->Get() == "yellow" );
	BOOST_CHECK( SEnum::Parse(etd, " green ")->Get() == "green" );

	BOOST_CHECK_THROW( SEnum::Parse(etd, ""), SException );
	BOOST_CHECK_THROW( SEnum::Parse(etd, "blue"), SException );
	BOOST_CHECK_THROW( SEnum::Parse(etd, "12"), SException );
	BOOST_CHECK_THROW( SEnum::Parse(etd, "'A'"), SException );
	BOOST_CHECK_THROW( SEnum::Parse(etd, "\"Hello\""), SException );
	BOOST_CHECK_THROW( SEnum::Parse(etd, "{}"), SException );
	BOOST_CHECK_THROW( SEnum::Parse(etd, "{10}"), SException );
	BOOST_CHECK_THROW( SEnum::Parse(etd, "{'A'}"), SException );
	BOOST_CHECK_THROW( SEnum::Parse(etd, "{\"Hello\"}"), SException );
	BOOST_CHECK_THROW( SEnum::Parse(etd, "{red}"), SException );
}


BOOST_AUTO_TEST_SUITE_END()
